/* Burk Labs Anachronistic Compiler Compiler (BLACC) v0.0
 * Generated from: 'test.blc'
 * on:             Wed Feb 06 20:47:47 2013

 */

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

extern unsigned GetNextToken(void);

#define BLC_GETINT(Ptr) ((Ptr)[0] | ((Ptr)[1]<<8))

#define BLC_OP_MATCH        (0)     /* MATCH        [token_id]      */
#define BLC_OP_CALL         (1)
#define BLC_OP_TAILSELECT   (2)
#define BLC_OP_LLSELECT     (3)
#define BLC_OP_ACTRED       (4)
#define BLC_OP_REDUCE       (5)
#define BLC_OP_HALT         (6)
#define BLC_OP_SHIFTSEL     (7)
#define BLC_OP_ACTION8      (8)
#define BLC_OP_LR0          (9)

#ifndef BLC_ASSERT
#define BLC_ASSERT  assert
#endif

typedef unsigned char   BLC_BYTE;

/* define token identifiers */
#define BLC_EOF                          (0)
#define BLC_MATCHANY                     (1)
#define BLC_NOACTION                     (0)
#define {}                               (2)
#define TK_FOO                           (3)
#define TK_INCR                          (4)
#define TK_DECR                          (5)
#define TK_IDENT                         (6)
#define TK_IF                            (7)
#define TK_ELSE                          (8)
#define TK_NUMBER                        (9)
#define TK_SIZEOF                        (10)


#if SCHAR_MAX >= 94 && SCHAR_MIN <= 0
    typedef signed char BLC_TOKVAL;
#elif SHRT_MAX >= 94 && SHRT_MIN <= 0
    typedef short BLC_TOKVAL;
#elif INT_MAX >= 94 && INT_MIN <= 0
    typedef int BLC_TOKVAL;
#else
    typedef long BLC_TOKVAL;
#endif
typedef unsigned char BLC_OPCODE;
typedef int BLC_VALTYPE;


/* Machine is a byte array that contains all the information
 * the parser needs to parse the given language.
 */
static BLC_BYTE Machine[195 /* 0x00C3 */] =
    {
    127,0,      /* [ 127] terminal symbol table size */
    19,0,       /* [  19] nonterminal symbol table size */
    2,0,        /* [   2] entry table size */
    16,0,       /* [  16] selection table size */
    21,0,       /* [  21] rule opcode table size */
/* Terminal symbol table */
    0,          /* [   0] 'BLC_EOF' */
    'B', 'L', 'C', 95, 
    'E', 'O', 'F',  0, 
    1,          /* [   1] 'BLC_MATCHANY' */
    'B', 'L', 'C', 95, 
    'M', 'A', 'T', 'C', 
    'H', 'A', 'N', 'Y', 
     0, 
    2,          /* [   2] '{}' */
    123, 125,  0, 
    3,          /* [   3] 'TK_FOO' */
    'T', 'K', 95, 'F', 
    'O', 'O',  0, 
    4,          /* [   4] 'TK_INCR' */
    'T', 'K', 95, 'I', 
    'N', 'C', 'R',  0, 
    5,          /* [   5] 'TK_DECR' */
    'T', 'K', 95, 'D', 
    'E', 'C', 'R',  0, 
    6,          /* [   6] 'TK_IDENT' */
    'T', 'K', 95, 'I', 
    'D', 'E', 'N', 'T', 
     0, 
    7,          /* [   7] 'TK_IF' */
    'T', 'K', 95, 'I', 
    'F',  0, 
    8,          /* [   8] 'TK_ELSE' */
    'T', 'K', 95, 'E', 
    'L', 'S', 'E',  0, 
    9,          /* [   9] 'TK_NUMBER' */
    'T', 'K', 95, 'N', 
    'U', 'M', 'B', 'E', 
    'R',  0, 
    10,         /* [  10] 'TK_SIZEOF' */
    'T', 'K', 95, 'S', 
    'I', 'Z', 'E', 'O', 
    'F',  0, 
    42,         /* [  42] ''*'' */
    39, 42, 39,  0, 
    43,         /* [  43] ''+'' */
    39, 43, 39,  0, 
    45,         /* [  45] ''-'' */
    39, 45, 39,  0, 
    47,         /* [  47] ''/'' */
    39, 47, 39,  0, 
    94,         /* [  94] ''^'' */
    39, 94, 39,  0, 
    0,          /* sentinel byte */
/* Nonterminal symbol table */
/* [0] Start */
    'S', 't', 'a', 'r', 
    't',  0, 
/* [1] list */
    'l', 'i', 's', 't', 
     0, 
/* [2] idents */
    'i', 'd', 'e', 'n', 
    't', 's',  0, 
    0,          /* sentinel byte */
/* entry table */
    0x00,0x00,  /* Start */
/* selection table */
/*0x0000:          LLSELECT body for 'Start' */
    0,          /* EOL (no token ranges) */
    0,          /* EOL (no token lists) */
/*0x0002:          LLSELECT body for 'list' */
    0,          /* EOL (no token ranges) */
    2,          /* 2 tokens for this rule */
    0x06,0x00,  /* 0x0006: address of rule */
    0,          /* BLC_EOF */
    6,          /* TK_IDENT */
    0,          /* EOL for token lists */
/*0x0009:          LLSELECT body for 'idents' */
    0,          /* EOL (no token ranges) */
    2,          /* 2 tokens for this rule */
    0x0C,0x00,  /* 0x000C: address of rule */
    0,          /* BLC_EOF */
    6,          /* TK_IDENT */
    0,          /* EOL for token lists */

/*0x00AE:          Begin opcodes */
/*[0x0000] <start> -> Start BLC_EOF */
    0x01,       /* BLCOP_CALL Start */
    0x0F,0x00,  
    0x00,       /* MATCH BLC_EOF */
    0,          
    0x06,       /* HALT */
/*[0x0006] list -> idents {A0} */
    0x03,       /* BLCOP_LLSELECT idents */
    0x09,0x00,  
    0x04,       /* BLCOP_ACTRED {A0} */
    0x01,       /*     rule# */
    0x01,       /*     <argcount> */
/*[0x000C] idents -> {A0} */
    0x04,       /* BLCOP_ACTRED {A0} */
    0x01,       /*     rule# */
    0x00,       /*     <argcount> */
/*[0x000F] Start -> list {A0} */
    0x01,       /* BLCOP_CALL list */
    0x06,0x00,  
    0x04,       /* BLCOP_ACTRED {A0} */
    0x01,       /*     rule# */
    0x01,       /*     <argcount> */

    };
    
typedef struct      BLC_STATE
    {
    BLC_BYTE*       Machine;
    BLC_BYTE*       TermSymtab;
    BLC_BYTE*       NontermSymtab;
    BLC_BYTE*       SelectData;
    BLC_BYTE*       Opcodes;
    unsigned        OpcodesSize;
    BLC_VALTYPE*    ValStack;
    BLC_VALTYPE*    VSP;
    size_t          ValStackSize;
    BLC_VALTYPE     ReturnValue;
    unsigned short* Stack;
    size_t          StackSize;
    unsigned        SP;             /* stack pointer (offset into Stack)            */
    BLC_BYTE*       IP;             /* instruction pointer (Opcodes offset)         */
    unsigned        CurrentToken;
    int             NStates;
    unsigned        LR0State;       /* current state # of LR(0) machine             */
    }           BLC_STATE;


static
const char* BlcTokstr(BLC_BYTE* Symtab, int Token)
    {
    while(*Symtab != Token)
        {
        while(*++Symtab)
            ;
        ++Symtab;   /* skip over NUL terminating byte */
        }
    /* skip token ID byte */
    ++Symtab;
    return Symtab;
    }

#ifndef BLC_PARSER_NAME
#define BLC_PARSER_NAME BlcParse
#endif

#ifndef BLC_NO_PARSER
/* BlcParse() - main parsing loop.
 */
int     BLC_PARSER_NAME(void)
    {
    BLC_STATE       State;
    unsigned        Count;
    unsigned        Opcode, Value, Address, Offset, ArgCount;
    BLC_BYTE*       Select;
    
    State.Machine           = Machine;
    Offset                  = 10;
    State.TermSymtab        = State.Machine + Offset;
    Offset                 += BLC_GETINT(State.Machine+0);
    State.NontermSymtab     = State.Machine + Offset;
    Offset                 += BLC_GETINT(State.Machine+2);
    Offset                 += BLC_GETINT(State.Machine+4);
    State.SelectData        = State.Machine + Offset;
    Offset                 += BLC_GETINT(State.Machine+6);
printf("opcode offset=0x%04X\n", Offset);
    State.Opcodes           = State.Machine + Offset;
    State.OpcodesSize       = BLC_GETINT(State.Machine+8);
    State.ValStackSize      = 100;
    State.ValStack          = (BLC_VALTYPE*)calloc(State.ValStackSize, sizeof(BLC_VALTYPE));
    State.VSP               = State.ValStack;
    State.StackSize         = 100;
    State.Stack             = (unsigned short*)calloc(State.StackSize, sizeof(unsigned short));
    State.SP                = 0;
    State.IP                = State.Opcodes;
    State.CurrentToken      = (BLC_BYTE)GetNextToken();
    for(;;)
    {
unsigned iStack;
    printf("[%d,%d]Opcode=0x%02X CurTok=%d(%s) IP=0x%04X  [0x%02X 0x%02X 0x%02X 0x%02X]\n",
        State.SP, State.VSP - State.ValStack, *State.IP,
        State.CurrentToken, BlcTokstr(State.TermSymtab, State.CurrentToken),
        (unsigned)(State.IP - State.Opcodes),
        State.IP[0], State.IP[1], State.IP[2], State.IP[3]);
printf("[");
for(iStack=0; iStack < State.SP; ++iStack)
    printf("0x%04X ", State.Stack[iStack]);
printf("]\n");
    Opcode      = *State.IP++;
    Value       = *State.IP++;
    switch(Opcode)
        {
        case    BLC_OP_MATCH :   /* match a particular token */
printf("MATCH %d (%s)\n", Value, BlcTokstr(State.TermSymtab, Value));
            if(Value == State.CurrentToken)
                {
                *State.VSP++       = Value;  
                State.CurrentToken = (BLC_BYTE)GetNextToken();
                continue;
                }
            fprintf(stderr, "Expecting token %d (%s), found %d (%s)\n", Value, BlcTokstr(State.TermSymtab, Value), State.CurrentToken, BlcTokstr(State.TermSymtab, State.CurrentToken));
            exit(1);
            break;
        case    BLC_OP_CALL :   /* [16-bit rule offset]     */
            Address     = Value | (*State.IP++ << 8);
printf("CALL 0x%04X\n", Address);
            ++State.VSP;            /* leave room for $$ */
            State.Stack[State.SP++] = (unsigned short)(State.IP - State.Opcodes);
            State.IP    = State.Opcodes + Address;
            break;
        case    BLC_OP_TAILSELECT   :   /* for left recursion       */
printf("TAILSELECT pops %d from value stack. (SP=%d, VSP=%d)\n", Value, State.SP, State.VSP - State.ValStack);
//            State.VSP  -= Value;
            assert(State.VSP >= State.ValStack);
            Value   = *State.IP++;
        case    BLC_OP_LLSELECT   :
            Address     = Value | (*State.IP++ << 8);
printf("Select offset: 0x%04X\n", Address);
            Select      = State.SelectData + Address;
            /* first come the token ranges */
            Count       = *Select++;
//printf("%d token ranges\n", Count);
            while(Count > 0)
                {
                Address     = BLC_GETINT(Select);
//printf("Address: 0x%04X\n", Address);
                Select     += 2;
                while(Count-- > 0)
                    if(State.CurrentToken >= Select[0] && State.CurrentToken <= Select[1])
                        goto SelectFound;
                    else
                        Select     += 2;
                Count       = *Select++;
                }
            /* Then we do groups (multiple values, single rule) */
            Count       = *Select++;
//printf("%d token groups\n", Count);
            while(Count > 0)
                {
                Address     = BLC_GETINT(Select);
//printf("Address: 0x%04X\n", Address);
                Select     += 2;
                for(; Count > 0; --Count)
                    if(*Select++ == State.CurrentToken)
                        goto SelectFound;
                Count       = *Select++;
                }
            /* no match on tail select just means no more tail recursion */
            if(Opcode == BLC_OP_TAILSELECT)
                {
                Value   = 0; /* already reduced value stack */
                goto Reduce;
                }
            /* no match for select! */
printf("No match for select!\n");
            exit(99);
SelectFound:
printf("SelectFound:\n");
            if(Opcode == BLC_OP_TAILSELECT)
                {
                /* copy $$ -> $1 */
//                State.VSP   -= TailPop;
                assert(State.VSP > State.ValStack);
                State.VSP[0]  = State.VSP[-1];
printf("++State.VSP\n");
                ++State.VSP;
                }
            else
                {
                assert(State.SP < 99);
                /* push address in current rule onto stack */
                State.Stack[State.SP++] = (unsigned short)(State.IP - State.Opcodes);
                ++State.VSP;            /* leave room for $$ */
                }
            State.IP      = &State.Opcodes[Address];
            break;
        case    BLC_OP_HALT : /* All done! */
printf("OP_HALT\n");
            return 0;
        case    BLC_OP_SHIFTSEL :   /* LR(0) state, non-accepting */
printf("OP_SHIFTSEL\n");
            Address     = Value | (*State.IP++ << 8);   /* address of select data */
            State.Stack[State.SP++] = (unsigned short)(State.IP-State.Opcodes); /* address of our GOTO */
            break;
        case    BLC_OP_ACTRED   :
        case    BLC_OP_ACTION8  : /* */
            ArgCount            = *State.IP++;
            if(Opcode == BLC_OP_ACTRED)
                State.ReturnValue   = State.VSP[-ArgCount];
printf("Perform action %d[%d] XXXXXXXX    ", Value, ArgCount);
            switch(Value)
                {
    case 1 :
        {
{A0}
        }
break;

                default :
                    assert(0); /* got illegal value for action number */
                }
            if(Opcode == BLC_OP_ACTRED)
                {
printf("VSP=%d, ArgCount=%d, %d\n", State.VSP-State.ValStack,ArgCount,-ArgCount-1);
                assert(State.VSP-State.ValStack > ArgCount);
                State.VSP[-ArgCount-1]  = State.ReturnValue;
                Value                   = ArgCount;
                }
            else
                {
                State.VSP[0] = State.ReturnValue;
                ++State.VSP;
                continue;
                }

        case    BLC_OP_REDUCE : /* [8-bit symbol count]       */
Reduce:
printf("reduce %d (SP=%d, VSP=%d)\n", Value, State.SP, (State.VSP - State.ValStack));
            assert(State.SP >= 1);
            assert((State.VSP - State.ValStack) >= 0);
            assert((State.VSP - State.ValStack) >= Value);
            State.VSP  -= Value;
            if(Opcode == BLC_OP_REDUCE)
                State.VSP[0] = State.VSP[1];
            if(State.IP[0] != BLC_OP_TAILSELECT)
                {
                State.SP   -= 1;
                Address     = State.Stack[State.SP];
                assert(Address < State.OpcodesSize);
                State.IP    = State.Opcodes + Address;
                }
            break;
        case BLC_OP_LR0 : /* begin parsing in (modified) LR(0) mode */
printf("BLC_OP_LR0\n");
            State.Stack[State.SP++]  = 0;  /* start in state 0 */
            
            break;
        default:
printf("Bad opcode: 0x%02X (%d)\n", Opcode, State.IP[-1]);
exit(99);
        }
    }
    }
#endif


#include <stdio.h>


